/**
 * Base table composable for HMI templates
 * 统一：参数、前端切片分页、排序、刷新流程
 */
import { ref, reactive, watch, unref, type Ref, type ComputedRef } from "vue";
import { CommonHmiDataAPI } from "@/api/hmi/common-hmi-data.api";

// 统一数据状态（供各模板复用）
export enum DATA_STATUS {
  WAITING = "waiting",
  SUCCESS = "success",
  ERROR = "error",
  NODATA = "nodata",
}
type MaybeRef<T> = T | Ref<T> | ComputedRef<T>;

export interface BaseTableOptions<TRow = any> {
  apiPath: MaybeRef<string>;
  pageSize?: MaybeRef<number | undefined>;
  /** 可以是 '1,2,3' 或 number[]，传空则不做分组过滤 */
  group?: MaybeRef<string | number[] | undefined>;
  /** 指定排序字段，不传则若存在 index 字段按 index 排序 */
  orderByKey?: MaybeRef<string | undefined>;
  /** 是否拼接定值区 /{displayZone} */
  showSettingZone?: MaybeRef<boolean | undefined>;
  displayZone?: MaybeRef<number | undefined>;
  /** 参数变化时是否重置到第一页，默认 true */
  resetOffsetOnParamsChange?: boolean;
  /** 可选：阻断拉取（例如编辑态不刷新） */
  fetchGuard?: () => boolean;
  /** 行数据格式化（默认仅附加 _index） */
  formatRow?: (raw: any, index: number) => TRow;
}

export function useBaseTableData<TRow = any>(options: BaseTableOptions<TRow>) {
  const tableData = ref<TRow[]>([]);
  const fullData = ref<TRow[]>([]);
  const total = ref(0);
  const loading = ref(false);
  const dataStatus = ref<DATA_STATUS>(DATA_STATUS.WAITING);

  const pagination = reactive({
    offset: 0,
    limit: toNumberOrDefault(options.pageSize, 10),
    group: parseGroup(unref(options.group)),
  });

  function parseGroup(group?: string | number[]): number[] {
    if (!group) return [];
    if (Array.isArray(group)) return group.map((g) => Number(g)).filter((g) => !Number.isNaN(g));
    return group
      .split(",")
      .map((g) => Number((g || "").trim()))
      .filter((g) => !Number.isNaN(g));
  }

  function toNumberOrDefault(v: MaybeRef<number | undefined>, def: number): number {
    const n = unref(v);
    return typeof n === "number" && !Number.isNaN(n) ? n : def;
  }

  function buildApiUrl(): string {
    const api = unref(options.apiPath);
    const showZone = !!unref(options.showSettingZone);
    const zone = unref(options.displayZone);
    if (showZone && zone !== undefined) {
      return `${api}/${zone}`;
    }
    return api;
  }

  function applySort(list: any[]): any[] {
    const arr = list.slice();
    const orderKey = unref(options.orderByKey);
    if (orderKey && orderKey.length > 0) {
      const key = orderKey;
      arr.sort((a, b) => {
        const valA = a[key];
        const valB = b[key];
        if (typeof valA === "number" && typeof valB === "number") return valA - valB;
        if (typeof valA === "string" && typeof valB === "string") return valA.localeCompare(valB);
        return 0;
      });
      return arr;
    }
    if (arr.length > 0 && Object.prototype.hasOwnProperty.call(arr[0], "index")) {
      arr.sort((a, b) => (a.index ?? 0) - (b.index ?? 0));
    }
    return arr;
  }

  function mapRows(raw: any[]): TRow[] {
    const fmt = options.formatRow ?? ((item: any, index: number) => ({ ...(item as any), _index: index }) as TRow);
    return raw.map((item, i) => fmt(item, i));
  }

  function sliceToPage() {
    tableData.value = fullData.value.slice(pagination.offset, pagination.offset + pagination.limit);
    total.value = fullData.value.length;
    return tableData.value;
  }

  async function fetchData() {
    if (!unref(options.apiPath)) return;
    loading.value = true;
    try {
      const apiUrl = buildApiUrl();
      const groupList = pagination.group ?? [];
      let res: any[] = [];
      if (groupList.length > 0) {
        res = await CommonHmiDataAPI.fetchGroupFiltedList(apiUrl, groupList);
      } else {
        res = await CommonHmiDataAPI.fetchFullList(apiUrl);
      }
      const rawList = Array.isArray(res) ? res : [];
      if (rawList.length === 0) {
        fullData.value = [];
        tableData.value = [];
        total.value = 0;
        dataStatus.value = DATA_STATUS.NODATA;
        return tableData.value;
      }
      const formatted = mapRows(applySort(rawList));
      fullData.value = formatted;
      dataStatus.value = DATA_STATUS.SUCCESS;
      return sliceToPage();
    } catch (err) {
      console.error("useBaseTableData.fetchData error:", err);
      dataStatus.value = DATA_STATUS.ERROR;
    } finally {
      loading.value = false;
    }
  }

  async function refreshData() {
    return await fetchData();
  }

  async function handlePaginationChange() {
    if (fullData.value && fullData.value.length > 0) {
      return sliceToPage();
    }
    return await fetchData();
  }

  // 监听关键参数变化，触发刷新
  watch(
    [
      () => unref(options.apiPath),
      () => unref(options.displayZone),
      () => unref(options.group),
      () => unref(options.orderByKey),
      () => unref(options.pageSize),
      () => unref(options.showSettingZone),
    ],
    async (_newVals, _oldVals) => {
      if (typeof options.fetchGuard === "function" && options.fetchGuard() === false) {
        return;
      }
      // pageSize 变化时同步 limit
      const newLimit = toNumberOrDefault(options.pageSize, pagination.limit);
      const limitChanged = newLimit !== pagination.limit;
      if (limitChanged) {
        pagination.limit = newLimit;
      }
      // group 变化时解析
      pagination.group = parseGroup(unref(options.group));

      // 参数变化默认回第一页
      if (options.resetOffsetOnParamsChange !== false) {
        pagination.offset = 0;
      }
      // console.log("useBaseTableData: options changed, refresh data");
      await fetchData();

      // 夹取越界页
      if (pagination.offset >= total.value && total.value > 0) {
        const maxPage = Math.max(1, Math.ceil(total.value / pagination.limit));
        pagination.offset = (maxPage - 1) * pagination.limit;
        sliceToPage();
      }
    },
    { flush: "post" }
  );

  return {
    tableData,
    total,
    loading,
    dataStatus,
    pagination,
    fetchData,
    refreshData,
    handlePaginationChange,
  };
}
